RENT A CAR

Private Monitoring System

Dashboard

Quick view ng negosyo mo.

MONTHLY RENTAL
₱0
Total booking value
COLLECTED
₱0
Reservation + payments
EXPENSES
₱0
For selected month
OUTSTANDING
₱0
Unpaid balances
ONGOING RENTALS
0
Units currently out
AVAILABLE TODAY
0
Active and not booked
FUTURE BOOKINGS
0
Upcoming reservations
NET CASH FLOW
₱0
Collected less expenses

6-Month Performance

Alerts

`); win.document.close(); } function findAvailability(){ const start=document.getElementById('avStart').value,end=document.getElementById('avEnd').value,cat=document.getElementById('avCategory').value; if(!start||!end)return toast('Piliin ang pickup at return date.'); if(endv.status==='ACTIVE'&&(cat==='ALL'||v.category===cat)&&isUnitAvailable(v.id,start,end)); const days=daysBetween(start,end); document.getElementById('availabilitySummary').innerHTML=`
Dates${dateDisplay(start)}–${dateDisplay(end)}
Rental Days${days}
Available Units${units.length}
Category${esc(cat==='ALL'?'All':cat)}
`; document.getElementById('availabilityResults').innerHTML=units.length?units.map(v=>`
${v.photo?``:`
🚙
`}
${esc(v.name)}
${esc(v.category)} • ${v.seats||'—'} seats
${money(v.dailyRate)}/day
`).join(''):`
Walang available unit sa selected dates.
`; } function bookAvailableUnit(unitId,start,end){ nav('bookings');openBookingModal(); document.getElementById('bPickup').value=start;document.getElementById('bReturn').value=end;refreshBookingUnits('',unitId); } function renderVehicles(){ const q=(document.getElementById('vehicleSearch')?.value||'').toLowerCase(); const rows=db.vehicles.filter(v=>`${v.name} ${v.plate} ${v.category}`.toLowerCase().includes(q)); const el=document.getElementById('vehiclesList'); if(!rows.length){el.innerHTML='
Wala pang vehicle. Tap “Add Unit.”
';return} el.innerHTML=rows.map(v=>`
${v.photo?``:`
🚙
`}
${esc(v.name)} ${statusBadge(v.status)}
${esc(v.plate||'No plate')} • ${esc(v.category)} • ${v.seats||'—'} seats
${money(v.dailyRate)}/day • ${v.ownershipType==='PARTNER'?'Partner: '+esc(v.ownerName||'—'):'Company-owned'}
`).join(''); } function openVehicleModal(id=''){ const v=id?byId(db.vehicles,id):null; const d={name:'',plate:'',category:db.settings.categories[0]||'SUV',seats:5,year:new Date().getFullYear(),dailyRate:0,status:'ACTIVE',ownershipType:'COMPANY',ownerName:'',commissionRate:20,odometer:0,nextPmsDate:'',registrationExpiry:'',insuranceExpiry:'',notes:'',photo:'',...v}; setModal(id?'Edit Vehicle':'Add Vehicle',`
Compressed automatically para hindi mabigat.
`, `${id?``:''}`); toggleOwnerFields(); } function toggleOwnerFields(){ const partner=document.getElementById('vOwnership')?.value==='PARTNER'; if(document.getElementById('ownerNameBox'))document.getElementById('ownerNameBox').style.display=partner?'block':'none'; if(document.getElementById('commissionBox'))document.getElementById('commissionBox').style.display=partner?'block':'none'; } async function imageToDataURL(file){ return new Promise((resolve,reject)=>{ const img=new Image(),reader=new FileReader(); reader.onload=e=>img.src=e.target.result;reader.onerror=reject; img.onload=()=>{ const max=700,scale=Math.min(1,max/Math.max(img.width,img.height)),c=document.createElement('canvas'); c.width=Math.round(img.width*scale);c.height=Math.round(img.height*scale);c.getContext('2d').drawImage(img,0,0,c.width,c.height); resolve(c.toDataURL('image/jpeg',.72)); };reader.readAsDataURL(file); }); } async function saveVehicleForm(id=''){ const name=document.getElementById('vName').value.trim();if(!name)return toast('Ilagay ang unit name.'); const old=id?byId(db.vehicles,id):null,file=document.getElementById('vPhoto').files[0]; let photo=old?.photo||'';if(file)photo=await imageToDataURL(file); const rec={id:id||uid('VHC'),name,plate:document.getElementById('vPlate').value.trim(),category:document.getElementById('vCategory').value, seats:num(document.getElementById('vSeats').value),year:document.getElementById('vYear').value,dailyRate:num(document.getElementById('vRate').value), status:document.getElementById('vStatus').value,ownershipType:document.getElementById('vOwnership').value, ownerName:document.getElementById('vOwner')?.value||'',commissionRate:num(document.getElementById('vCommission')?.value), odometer:num(document.getElementById('vOdometer').value),nextPmsDate:document.getElementById('vPms').value, registrationExpiry:document.getElementById('vReg').value,insuranceExpiry:document.getElementById('vInsurance').value, notes:document.getElementById('vNotes').value,photo,createdAt:old?.createdAt||new Date().toISOString()}; if(old)Object.assign(old,rec);else db.vehicles.push(rec);saveDB();closeModal();toast('Vehicle saved.'); } function deleteVehicle(id){ if(db.bookings.some(b=>b.unitId===id))return toast('May booking record ang unit; set it to INACTIVE instead.'); if(!confirm('Delete this vehicle?'))return;db.vehicles=db.vehicles.filter(x=>x.id!==id);saveDB();closeModal(); } function renderCustomers(){ const q=(document.getElementById('customerSearch')?.value||'').toLowerCase(); const rows=db.customers.filter(c=>`${c.name} ${c.contact}`.toLowerCase().includes(q)); const el=document.getElementById('customersTable'); if(!rows.length){el.innerHTML='
Wala pang customer record.
';return} el.innerHTML=`
${rows.map(c=>``).join('')}
NameContactLicenseAddressAction
${esc(c.name)}${esc(c.contact||'—')}${esc(c.licenseType||'—')}
${esc(c.licenseNo||'')}
${esc(c.address||'—')}
`; } function openCustomerModal(id=''){ const c=id?byId(db.customers,id):null,d={name:'',contact:'',address:'',licenseType:'Philippine License',licenseNo:'',notes:'',...c}; setModal(id?'Edit Customer':'Add Customer',`
`, `${id?``:''}`); } function saveCustomerForm(id=''){ const name=document.getElementById('cName').value.trim();if(!name)return toast('Ilagay ang customer name.'); const old=id?byId(db.customers,id):null,rec={id:id||uid('CUS'),name,contact:document.getElementById('cContact').value.trim(), address:document.getElementById('cAddress').value.trim(),licenseType:document.getElementById('cLicenseType').value, licenseNo:document.getElementById('cLicenseNo').value.trim(),notes:document.getElementById('cNotes').value,createdAt:old?.createdAt||new Date().toISOString()}; if(old)Object.assign(old,rec);else db.customers.push(rec);saveDB();closeModal();toast('Customer saved.'); } function deleteCustomer(id){ if(db.bookings.some(b=>b.customerId===id))return toast('May booking record ang customer kaya hindi puwedeng i-delete.'); if(!confirm('Delete this customer?'))return;db.customers=db.customers.filter(x=>x.id!==id);saveDB();closeModal(); } function renderExpenses(){ const monthEl=document.getElementById('expenseMonthFilter');if(!monthEl.value)monthEl.value=monthNow(); const cat=document.getElementById('expenseCategoryFilter')?.value||'ALL'; const rows=[...db.expenses].filter(e=>e.date.slice(0,7)===monthEl.value&&(cat==='ALL'||e.category===cat)).sort((a,b)=>b.date.localeCompare(a.date)); const total=rows.reduce((s,e)=>s+num(e.amount),0); document.getElementById('expenseSummary').innerHTML=`
Selected Month${esc(monthEl.value)}
Records${rows.length}
Total Expenses${money(total)}
Category${esc(cat)}
`; const el=document.getElementById('expensesTable'); el.innerHTML=rows.length?`
${rows.map(e=>``).join('')}
DateCategoryDescriptionAmountAction
${dateDisplay(e.date)}${esc(e.category)}${esc(e.description)}${money(e.amount)}
`:'
Walang expenses sa selected month.
'; } function openExpenseModal(id=''){ const e=id?byId(db.expenses,id):null,d={date:today(),category:db.settings.expenseCategories[0],description:'',amount:0,...e}; setModal(id?'Edit Expense':'Add Expense',`
`, `${id?``:''}`); } function saveExpenseForm(id=''){ const desc=document.getElementById('eDescription').value.trim(),amount=num(document.getElementById('eAmount').value); if(!desc||amount<=0)return toast('Ilagay ang description at amount.'); const old=id?byId(db.expenses,id):null,rec={id:id||uid('EXP'),date:document.getElementById('eDate').value,category:document.getElementById('eCategory').value,description:desc,amount,createdAt:old?.createdAt||new Date().toISOString()}; if(old)Object.assign(old,rec);else db.expenses.push(rec);saveDB();closeModal();toast('Expense saved.'); } function deleteExpense(id){if(!confirm('Delete this expense?'))return;db.expenses=db.expenses.filter(x=>x.id!==id);saveDB();closeModal()} function renderMaintenance(){ const rows=[...db.maintenance].sort((a,b)=>(a.dueDate||'9999').localeCompare(b.dueDate||'9999')); const el=document.getElementById('maintenanceTable'); if(!rows.length){el.innerHTML='
Wala pang maintenance record.
';return} el.innerHTML=`
${rows.map(m=>``).join('')}
UnitTypeDue DateOdometer DueCostStatusAction
${esc(m.unitName)}${esc(m.type)}${dateDisplay(m.dueDate)}${m.odometerDue?num(m.odometerDue).toLocaleString():'—'}${money(m.cost)}${statusBadge(m.status)}
`; } function openMaintenanceModal(id=''){ if(!db.vehicles.length)return toast('Mag-add muna ng vehicle.'); const m=id?byId(db.maintenance,id):null,d={unitId:db.vehicles[0].id,type:'PMS',dueDate:'',odometerDue:0,status:'SCHEDULED',cost:0,notes:'',...m}; setModal(id?'Edit Maintenance':'Add Maintenance',`
`, `${id?``:''}`); } function saveMaintenanceForm(id=''){ const unit=byId(db.vehicles,document.getElementById('mtUnit').value),old=id?byId(db.maintenance,id):null; const rec={id:id||uid('MNT'),unitId:unit.id,unitName:unit.name,type:document.getElementById('mtType').value,status:document.getElementById('mtStatus').value, dueDate:document.getElementById('mtDue').value,odometerDue:num(document.getElementById('mtOdo').value),cost:num(document.getElementById('mtCost').value), notes:document.getElementById('mtNotes').value,createdAt:old?.createdAt||new Date().toISOString()}; if(old)Object.assign(old,rec);else db.maintenance.push(rec);saveDB();closeModal();toast('Maintenance saved.'); } function deleteMaintenance(id){if(!confirm('Delete this record?'))return;db.maintenance=db.maintenance.filter(x=>x.id!==id);saveDB();closeModal()} function renderPayouts(){ const rows=[...db.payouts].sort((a,b)=>(b.dueDate||'').localeCompare(a.dueDate||'')); const el=document.getElementById('payoutsTable'); if(!rows.length){el.innerHTML='
Wala pang partner-owned booking payout.
';return} el.innerHTML=`
${rows.map(p=>``).join('')}
BookingOwner / UnitGrossCommissionCompany ShareOwner ShareDueStatusAction
${esc(p.bookingId)}${esc(p.ownerName)}
${esc(p.unitName)}
${money(p.gross)}${p.commission}%${money(p.companyShare)}${money(p.ownerShare)}${dateDisplay(p.dueDate)}${statusBadge(p.status)}
`; } function togglePayout(id){const p=byId(db.payouts,id);p.status=p.status==='PAID'?'PENDING':'PAID';p.paidDate=p.status==='PAID'?today():'';saveDB();toast('Payout status updated.')} function renderSettings(){ document.getElementById('setBusinessName').value=db.settings.businessName||''; document.getElementById('setContact').value=db.settings.contactNumber||''; document.getElementById('setCategories').value=db.settings.categories.join(', '); document.getElementById('setExpenseCategories').value=db.settings.expenseCategories.join(', '); } function saveSettings(){ const categories=document.getElementById('setCategories').value.split(',').map(x=>x.trim()).filter(Boolean); const exps=document.getElementById('setExpenseCategories').value.split(',').map(x=>x.trim()).filter(Boolean); db.settings.businessName=document.getElementById('setBusinessName').value.trim()||'RENT A CAR'; db.settings.contactNumber=document.getElementById('setContact').value.trim(); if(categories.length)db.settings.categories=categories;if(exps.length)db.settings.expenseCategories=exps; saveDB();toast('Settings saved.'); } function openBackupModal(){nav('settings')} function exportBackup(){ const blob=new Blob([JSON.stringify(db,null,2)],{type:'application/json'}),a=document.createElement('a'); a.href=URL.createObjectURL(blob);a.download=`Rent_A_Car_Backup_${today()}.json`;a.click();URL.revokeObjectURL(a.href);toast('Backup downloaded.'); } function restoreBackup(e){ const file=e.target.files[0];if(!file)return; const r=new FileReader();r.onload=()=>{ try{const data=JSON.parse(r.result);if(!data.settings||!Array.isArray(data.bookings))throw new Error();if(confirm('Replace current data with this backup?')){db=Object.assign(defaultDB(),data);saveDB();toast('Backup restored.')}}catch(err){toast('Invalid backup file.')} e.target.value=''; };r.readAsText(file); } function resetAllData(){ if(!confirm('This will delete ALL records in this browser. Continue?'))return; if(!confirm('Final confirmation: delete everything?'))return; db=defaultDB();saveDB();toast('All data reset.'); } function loadDemoData(){ if(db.vehicles.length||db.customers.length||db.bookings.length){if(!confirm('Demo data will be added to existing records. Continue?'))return} const v1={id:uid('VHC'),name:'Toyota Fortuner 2026',plate:'',category:'SUV',seats:7,year:2026,dailyRate:3500,status:'ACTIVE',ownershipType:'COMPANY',ownerName:'',commissionRate:0,odometer:0,nextPmsDate:'',registrationExpiry:'',insuranceExpiry:'',notes:'',photo:'',createdAt:new Date().toISOString()}; const v2={id:uid('VHC'),name:'Mitsubishi Mirage G4 2026',plate:'',category:'Sedan',seats:5,year:2026,dailyRate:1800,status:'ACTIVE',ownershipType:'COMPANY',ownerName:'',commissionRate:0,odometer:0,nextPmsDate:'',registrationExpiry:'',insuranceExpiry:'',notes:'',photo:'',createdAt:new Date().toISOString()}; const c={id:uid('CUS'),name:'Sample Customer',contact:'09123456789',address:'',licenseType:'Philippine License',licenseNo:'',notes:'',createdAt:new Date().toISOString()}; db.vehicles.push(v1,v2);db.customers.push(c);saveDB();toast('Demo data loaded.'); } function exportBookingsCSV(){ const headers=['Booking ID','Pickup Date','Return Date','Customer','Contact','Unit','Booking Daily Rate','Rental Days','Total Rental Price','Paid','Balance','Status','Source']; const rows=db.bookings.map(b=>[b.id,b.pickupDate,b.returnDate,b.customerName,b.contact,b.unitName,b.dailyRate,b.rentalDays,b.total,b.amountPaid,b.balance,liveBookingStatus(b),b.source]); const csv=[headers,...rows].map(r=>r.map(v=>`"${String(v??'').replaceAll('"','""')}"`).join(',')).join('\n'); const blob=new Blob([csv],{type:'text/csv;charset=utf-8'}),a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download=`Bookings_${today()}.csv`;a.click();URL.revokeObjectURL(a.href); } function setModal(title,body,foot){ document.getElementById('modalTitle').textContent=title;document.getElementById('modalBody').innerHTML=body;document.getElementById('modalFoot').innerHTML=foot;document.getElementById('modal').classList.add('show'); } function closeModal(){document.getElementById('modal').classList.remove('show')} function toast(msg){const el=document.getElementById('toast');el.textContent=msg;el.classList.add('show');clearTimeout(window._toast);window._toast=setTimeout(()=>el.classList.remove('show'),2800)} document.addEventListener('keydown',e=>{if(e.key==='Escape')closeModal()}); (function init(){ document.getElementById('dashboardMonth').value=monthNow(); document.getElementById('bookingMonthFilter').value=''; document.getElementById('expenseMonthFilter').value=monthNow(); document.getElementById('avStart').value=today(); const tomorrow=new Date(Date.now()+86400000).toISOString().slice(0,10); document.getElementById('avEnd').value=tomorrow; renderAll(); nav('dashboard'); })();